package org.jython_on_android;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.util.Properties;
import java.lang.reflect.Method;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import org.python.util.PythonInterpreter;
public class JythonOnAndroidRunScript extends Activity {
public final static int ID = R.raw.main;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
copyResourcesToLocal();
Properties props = new Properties();
props.setProperty("python.path", this.getFilesDir().getAbsolutePath());
PythonInterpreter.initialize(System.getProperties(), props, new String[] {""});
PythonInterpreter interp = new PythonInterpreter();
String main_file = this.getFilesDir().getAbsolutePath() + "/main.jython";
Log.d("Jython-For-Android", "main_file = " + main_file);
interp.execfile(main_file);
}
public void copyResourcesToLocal() {
String name, sFileName;
InputStream content;
R.raw a = new R.raw();
java.lang.reflect.Field[] t = R.raw.class.getFields();
Resources resources = getResources();
for (int i = 0; i < t.length; i++) {
try {
name = resources.getText(t[i].getInt(a)).toString();
Log.d("Jython-For-Android", "Copying " + i + " - " + name);
sFileName = name.substring(name.lastIndexOf("res/raw/") + 8, name .length());
Log.d("Jython-For-Android", "Copying " + i + " - " + sFileName);
content = getResources().openRawResource(t[i].getInt(a));
// Copies script to internal memory only if changes were made
sFileName = this.getFilesDir()
.getAbsolutePath()
+ "/" + sFileName;
if (needsToBeUpdated(sFileName, content)) {
Log.d("Jython-For-Android", "Copying from stream " + sFileName);
content.reset();
this.copyFromStream(sFileName, content);
}
this.chmod(new File(sFileName), 0755);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public boolean needsToBeUpdated(String filename, InputStream content) {
File script = new File(filename);
FileInputStream fin;
Log.d("Jython-For-Android", "Checking if " + filename + " exists");
if (!script.exists()) {
Log.d("Jython-For-Android", "not found");
return true;
}
Log.d("Jython-For-Android", "Comparing file with content");
try {
fin = new FileInputStream(filename);
int c;
while ((c = fin.read()) != -1) {
if (c != content.read()) {
Log.d("Jython-For-Android", "Something changed replacing");
return true;
}
}
} catch (Exception e) {
Log.d("Jython-For-Android", "Something failed during comparing");
Log.e("Jython-For-Android", e.toString());
return true;
}
Log.d("Jython-For-Android", "No need to update " + filename);
return false;
}
public File copyFromStream(String name, InputStream input) {
if (name == null || name.length() == 0) {
Log.e("Jython-For-Android", "No script name specified.");
return null;
}
File file = new File(name);
if (!makeDirectories(file.getParentFile(), 0755)) {
return null;
}
try {
OutputStream output = new FileOutputStream(file);
copy(input, output);
} catch (Exception e) {
Log.e("Jython-For-Android", e.toString());
return null;
}
return file;
}
private static final int BUFFER_SIZE = 1024 * 8;
public int copy(InputStream input, OutputStream output) throws Exception, IOException {
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
int count = 0, n = 0;
try {
while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n);
count += n;
}
out.flush();
} finally {
try {
out.close();
} catch (IOException e) {
Log.e(e.getMessage(), e.toString());
}
try {
in.close();
} catch (IOException e) {
Log.e(e.getMessage(), e.toString());
}
}
return count;
}
public static int chmod(File path, int mode) throws Exception {
Class<?> fileUtils = Class.forName("android.os.FileUtils");
Method setPermissions =
fileUtils.getMethod("setPermissions", String.class, int.class, int.class, int.class);
return (Integer) setPermissions.invoke(null, path.getAbsolutePath(), mode, -1, -1);
}
public boolean makeDirectories(File directory, int mode) {
File parent = directory;
while (parent.getParentFile() != null && !parent.exists()) {
parent = parent.getParentFile();
}
if (!directory.exists()) {
Log.v("Jython-For-Android", "Creating directory: " + directory.getName());
if (!directory.mkdirs()) {
Log.e("Jython-For-Android", "Failed to create directory.");
return false;
}
}
try {
this.recursiveChmod(parent, mode);
} catch (Exception e) {
Log.e("Jython-For-Android", e.toString());
return false;
}
return true;
}
public boolean recursiveChmod(File root, int mode) throws Exception {
boolean success = this.chmod(root, mode) == 0;
for (File path : root.listFiles()) {
if (path.isDirectory()) {
success = this.recursiveChmod(path, mode);
}
success &= (this.chmod(path, mode) == 0);
}
return success;
}
}